import os
import shutil
from typing import List

import cv2
import numpy as np
from loguru import logger


class ClickCrack:
    """显示图片, 双击返回坐标, ESC 退出并返回结果"""

    def __init__(self, bg: bytes, small_imgs: bytes or List[bytes] = None):
        """

        :param bg: 底图
        :param small_imgs: 小图 (列表) 用于显示点击顺序, 可不传
        """
        self.bg = bg
        self.small_imgs = [small_imgs] if small_imgs and isinstance(small_imgs, bytes) else small_imgs
        self.points = []

    def add_point(self, event, x, y, *args, **kwargs):
        if event == cv2.EVENT_LBUTTONDBLCLK:
            self.points.append((x, y))
            logger.debug(f"当前点击: {(x, y)}")

    def discern(self):
        if self.small_imgs:
            for i, img in enumerate(self.small_imgs):
                if not os.path.exists("tmp"):
                    os.mkdir("tmp")
                cv2.imwrite(f"tmp/{i}.png", cv2.imdecode((np.frombuffer(img, np.uint8)), cv2.IMREAD_UNCHANGED))
            logger.info("需要点击的小图顺序已写入 tmp 文件夹")
        logger.info(f"开始点击, 双击确定坐标, 点击完毕后按 ESC 退出")
        cv2.namedWindow("image", cv2.WINDOW_NORMAL)
        cv2.setMouseCallback("image", self.add_point)
        cv2.imshow("image", cv2.imdecode((np.frombuffer(self.bg, np.uint8)), cv2.IMREAD_UNCHANGED))
        while True:
            if cv2.waitKey(20) & 0xFF == 27:  # 按ESC退出
                break
        cv2.destroyAllWindows()
        if os.path.exists("tmp"):
            shutil.rmtree("tmp")
        return self.points


if __name__ == '__main__':
    with open(r'123.jpg', 'rb') as f:
        bg = f.read()
    cc = ClickCrack(bg=bg).discern()
    print(cc)
    print([(x / 344 * 100, y / (384 - 45) * 100) for x, y in cc])
